﻿#include "memory_chunk.h"
#include <cstddef>
#include <cstdlib>
using namespace RemoteObj;

MemoryChunk::MemoryChunk(int32_t size, int32_t count): _freelist(NULL), _size(size), _count(0)
{
    MemoryBlock* block;
    while(count--)
    {
        block = create_block();
        if(!block)
            break;
        block->data.next = _freelist;
        _freelist = block;
    }
   // _sem.signal();
}

MemoryChunk::~MemoryChunk()
{
    MemoryBlock* block;
    while(NULL != (block = _freelist))
    {
        _freelist = block->data.next;
        delete_block(block);
    }
}

MemoryBlock* MemoryChunk::create_block()
{
    MemoryBlock* block=(MemoryBlock*)::malloc(sizeof(BlockHeader) + _size);

    if(block)
    {

        block->header.chunk = this;
        block->header.len = _size;

        ++_count;
    }
    return block;
}

void* MemoryChunk::malloc()
{
    //_sem.wait();
    MemoryBlock* block;
    if(_freelist)
    {
        block = _freelist;
        _freelist = block->data.next;
    }
    else
    {
        if(!(block = create_block()))
        {
            _sem.signal();
            return NULL;
        }
    }
   // _sem.signal();
    return &block->data.buffer;
}

void MemoryChunk::free(void* mem)
{
    MemoryBlock* block = (MemoryBlock*)((char*)mem-sizeof(BlockHeader));
    block->header.chunk->free(block);
}

void MemoryChunk::free(MemoryBlock* block)
{
    //_sem.wait();
    block->data.next = _freelist;
    _freelist = block;
   // _sem.signal();
}


void MemoryChunk::delete_block(MemoryBlock* block)
{
    ::free(block);
}
